module SRAM_2_AXI_bridge (

    /*AXI SIGNALS!*/
    //clk and reset
    input aclk,
    input aresetn,

    //Read request channel
    output [ 3:0] arid,
    output [31:0] araddr,
    output [ 7:0] arlen,
    output [ 2:0] arsize,
    output [ 1:0] arburst,
    output [ 1:0] arlock,
    output [ 3:0] arcache,
    output [ 2:0] arprot,
    output        arvalid,
    input         arready,

    //Read response channel
    input [ 3:0] rid,
    input [31:0] rdata,
    input [ 1:0] rresp,
    input        rlast,
    input        rvalid,
    output       rready,

    //Write request channel
    output [ 3:0] awid,
    output [31:0] awaddr,
    output [ 7:0] awlen,
    output [ 2:0] awsize,
    output [ 1:0] awburst,
    output [ 1:0] awlock,
    output [ 3:0] awcache,
    output [ 2:0] awprot,
    output        awvalid,
    input         awready,

    //Write data channel
    output [ 3:0] wid,
    output [31:0] wdata,
    output [ 3:0] wstrb,
    output        wlast,
    output        wvalid,
    input         wready,

    //Write response
    input [ 3:0] bid,
    input [ 1:0] bresp,
    input        bvalid,
    output       bready,

    /*SRAM SIGNALS*/
    //Inst SRAM
    input         inst_sram_req,
    input         inst_sram_wr,
    input  [ 1:0] inst_sram_size,
    input  [31:0] inst_sram_addr,
    input  [ 3:0] inst_sram_wstrb,
    input  [31:0] inst_sram_wdata,
    output        inst_sram_addr_ok,
    output        inst_sram_data_ok,
    output [31:0] inst_sram_rdata,

    //Data SRAM
    input         data_sram_req,
    input         data_sram_wr,
    input  [ 1:0] data_sram_size,
    input  [31:0] data_sram_addr,
    input  [ 3:0] data_sram_wstrb,
    input  [31:0] data_sram_wdata,
    output        data_sram_addr_ok,
    output        data_sram_data_ok,
    output [31:0] data_sram_rdata

);

assign arlen = 8'd0;
assign arburst = 2'b01;
assign arlock = 2'b00;
assign arcache = 4'd0;
assign arprot = 3'd0;
assign awid = 4'd1;
assign awlen = 8'd0;
assign awburst = 2'b01;
assign awlock = 2'b0;
assign awcache = 4'b0;
assign awprot = 3'b0;
assign wid = 4'b1;
assign wlast = 1'b1;

reg [3:0] arid_r;
wire read_request_valid;
reg axi_is_req;
assign read_request_valid = ~axi_is_req && ((inst_sram_req && ~inst_sram_wr) || (data_sram_req && ~data_sram_wr));
always @(posedge aclk ) begin
    if (~aresetn) begin
        arid_r <= 2'b0;
    end
    else if (read_request_valid) begin
        arid_r <= (data_sram_req && ~data_sram_wr) ? 4'd1 : 4'd0;
    end
    else if (axi_is_req && arvalid && arready) begin
        arid_r <= 2'b0;
    end
end
assign arid = arid_r;

reg [31:0] araddr_r;
always @(posedge aclk ) begin
    if (~aresetn) begin
        araddr_r <= 32'b0;
    end
    else if (read_request_valid) begin
        araddr_r <= (data_sram_req && ~data_sram_wr) ? data_sram_addr : inst_sram_addr;
    end
    /*else if (axi_is_req && arvalid && arready) begin
        arid_r <= 2'b0;
    end*/
end
assign araddr = araddr_r;

reg [2:0] arsize_r;

always @(posedge aclk ) begin
    if (~aresetn) begin
        arsize_r <= 3'b0;
    end
    else if (read_request_valid) begin
        arsize_r[1:0] <= (data_sram_req && ~data_sram_wr) ? data_sram_size : inst_sram_size;
    end
end
assign arsize = arsize_r;

reg arvalid_r;
always @(posedge aclk ) begin
    if (~aresetn) begin
        arvalid_r <= 1'b0;
    end
    else if (read_request_valid) begin
        arvalid_r <= 1'b1;
    end
    else if (arvalid && arready) begin
        arvalid_r <= 1'b0;
    end
end
assign arvalid = arvalid_r;

always @(posedge aclk ) begin
    if (~aresetn) begin
        axi_is_req <= 1'b0;
    end
    else if (read_request_valid) begin
        axi_is_req <= 1'b1;
    end
    else if (axi_is_req && rvalid && rready) begin
        axi_is_req <= 1'b0;
    end
end

// 0:empty 1:data 2:inst
reg[1:0] read_status;
always @(posedge aclk ) begin
    if (~aresetn) begin
        read_status <= 2'b0;
    end
    else if (read_request_valid && (data_sram_req && ~data_sram_wr)) begin
        read_status <= 2'b1;
    end
    else if (read_request_valid && (inst_sram_req && ~inst_sram_wr)) begin
        read_status <= 2'd2;
    end
    else if (axi_is_req && rvalid && rready) begin
        read_status <= 2'b0;
    end
end
    
assign inst_sram_addr_ok = ~axi_is_req && (inst_sram_req && ~inst_sram_wr) && ~(data_sram_req && ~data_sram_wr);
assign data_sram_addr_ok = (~axi_is_req && (data_sram_req && ~data_sram_wr)) || (awready);
assign inst_sram_rdata = (read_status == 2'd2) ? rdata : 32'b0; //_r
assign data_sram_rdata = (read_status == 2'b1) ? rdata : 32'b0; //_r


reg rvalid_r;
assign inst_sram_data_ok = (read_status == 2'd2) && rvalid;
assign data_sram_data_ok = ( axi_is_req &&(read_status == 2'b1) && rvalid) || (axi_write_state == 2'd3 && bvalid);
always @(posedge aclk ) begin
    if (~aresetn) begin
        rvalid_r <= 1'b0;
    end
    else if (rvalid) begin
        rvalid_r <= 1'b1;
    end
end

reg [31:0] rdata_r;
assign rready = 1'b1;
always @(posedge aclk) begin
    if (~aresetn) begin
        rdata_r <= 32'b0;
    end
    else if (rvalid && rready) begin
        rdata_r <= rdata;
    end
end

//state in state machine
reg [1:0] axi_write_state;



wire write_request_valid;
assign write_request_valid = (axi_write_state == 2'b0) && ((data_sram_req && data_sram_wr) || (inst_sram_req && inst_sram_wr));
always @(posedge aclk ) begin
    if (~aresetn) begin
        axi_write_state <= 2'b0;
    end
    else if ((axi_write_state == 2'b0) && write_request_valid) begin
        axi_write_state <= 2'd1;
    end
    else if ((axi_write_state == 2'd1) && awvalid && awready) begin
        axi_write_state <= 2'd2;
    end
    else if ((axi_write_state == 2'd2) && wvalid && wready) begin
        axi_write_state <= 2'd3;
    end
    else if ((axi_write_state == 2'd3) && bvalid && bready) begin
        axi_write_state <= 2'd0;
    end
end

reg [31:0] awaddr_r;
always @(posedge aclk ) begin
    if (~aresetn) begin
        awaddr_r <= 32'b0;
    end
    else if (write_request_valid) begin
        awaddr_r <= data_sram_addr;
    end
    /*else if (axi_is_req_w && wvalid && wready) begin
        axi_is_req_w <= 1'b0;
    end*/
end
assign awaddr = awaddr_r;

reg [2:0] awsize_r;
always @(posedge aclk ) begin
    if (~aresetn) begin
        awsize_r <= 32'b0;
    end
    else if (write_request_valid) begin
        awsize_r <= data_sram_addr;
    end
    /*else if (axi_is_req_w && wvalid && wready) begin
        axi_is_req_w <= 1'b0;
    end*/
end
assign awsize = awsize_r;

reg awvalid_r;
always @(posedge aclk ) begin
    if (~aresetn) begin
        awvalid_r <= 1'b0;
    end
    else if (write_request_valid) begin
        awvalid_r <= 1'b1;
    end
    else if (awvalid && awready) begin
        awvalid_r <= 1'b0;
    end
end
assign awvalid = awvalid_r;

reg [31:0] wdata_r;
always @(posedge aclk) begin
    if (~aresetn) begin
        wdata_r <= 32'b0;
    end
    else if (write_request_valid) begin
        wdata_r <= data_sram_wdata;
    end
end
assign wdata = wdata_r;

reg [3:0] wstrb_r;
always @(posedge aclk) begin
    if (~aresetn) begin
        wstrb_r <= 4'b0;
    end
    else if (write_request_valid) begin
        wstrb_r <= data_sram_wstrb;
    end
end
assign wstrb = wstrb_r;

reg wvalid_r;
always @(posedge aclk) begin
    if (~aresetn) begin
        wvalid_r <= 4'b0;
    end
    else if (axi_write_state == 2'd2) begin
        wvalid_r <= 1'b1;
    end
    else if (wvalid && wready) begin
        wvalid_r <= 1'b0;
    end
end
assign wvalid = wvalid_r;

reg bready_r;
always @(posedge aclk) begin
    if (~aresetn) begin
        bready_r <= 4'b0;
    end
    else if (axi_write_state == 2'd3) begin
        bready_r <= 1'b1;
    end
    else if (bvalid && bready) begin
        bready_r <= 1'b0;
    end
end
assign bready = bready_r;

endmodule 